import { Scene } from '@babylonjs/core/scene';
import { Button } from '@babylonjs/gui/2D/controls/button';
import { CreateHandleTo, ICallback, IHandle, RemoveHandle } from '../../data/data-handle';
import { IUIRectangleOptions, UIRectangle } from './ui-rectangle';
import { Image } from '@babylonjs/gui/2D/controls/image';
import { Control } from '@babylonjs/gui/2D/controls/control';


/**
 * 按钮控件参数对象
 * @param text 文字内容
 * @param imageUrl 图像链接
 * @param fontColor 文字颜色
 * @param fontSize 文字大小
 * @param fontFamily 字体
 * @param imageStretch 图像拉伸模式
 */
interface IUIButtonOptions extends IUIRectangleOptions {
    text?: string,
    imageUrl?: string,
    fontColor?: string,
    fontSize?: number,
    fontFamily?: string,
    imageStretch?: number,
}


/**
 * 按钮控件
 * @param name 名称
 * @param scene 所在场景
 * @param options 参数对象
 */
class UIButton extends UIRectangle {

    private _clickHandles: Array<IHandle<undefined>> = [];
    private _url!: string | null;

    constructor(name: string, scene: Scene, options?: IUIButtonOptions) {
        super(name, scene, options);
    }

    /**
     * 设置文字内容
     */
    public set text(text: string) {
        (this.control as Button).textBlock!.text = text;
    }

    /**
     * 获取文字内容
     */
    public get text(): string {
        return (this.control as Button).textBlock!.text;
    }

    /**
     * 设置纹理
     */
    public set imageUrl(url: string) {
        const img = (this.control as Button).image;
        if (!img) return;
        img.source = url;
    }

    /**
     * 获取纹理
     */
    public get imageUrl(): string {
        const img = (this.control as Button).image;
        if (!img) return '';
        const source = img.source;
        return source ? source : '';
    }

    /**
     * 设置字体颜色
     */
    public set fontColor(color: string) {
        (this.control as Button).color = color;
    }

    /**
     * 获取字体颜色
     */
    public get fontColor(): string {
        return (this.control as Button).color;
    }

    /**
     * 添加点击回调函数
     * @param func 回调函数
     * @returns 回调函数对象
     */
    public onClick(func: ICallback<undefined>): IHandle<undefined> {
        return CreateHandleTo(func, this._clickHandles);
    }

    /**
     * 移除点击回调函数对象
     * @param handle 回调函数对象或其id
     */
    public removeClickHandle(handle: number | IHandle<undefined>): void {
        RemoveHandle(handle, this._clickHandles);
    }

    protected initializeControl(name: string, scene: Scene, options: IUIButtonOptions): Button {
        this._url = options.imageUrl || null;
        const btn = this._url ?
            Button.CreateImageOnlyButton(name + '-button', this._url) :
            Button.CreateSimpleButton(name + '-button', options.text || 'button');
        btn.background = options.background || '#000000';
        btn.color = options.fontColor || '#ffffff';
        btn.fontSize = options.fontSize || 26;
        btn.fontFamily = options.fontFamily || 'Arial';
        btn.cornerRadius = options.cornerRadius || 0;
        btn.thickness = options.borderThickness || 0;
        if (btn.image) btn.image.stretch = options.imageStretch === undefined ? Image.STRETCH_FILL : options.imageStretch;
        return btn;
    }

    protected bindEvent(control: Button, options: IUIButtonOptions): void {
        super.bindEvent(control, options);
        control.onPointerClickObservable.add(() => {
            if (!this.isEnabled) return;
            if (!this.avoidEventHandle) this._clickHandles.forEach(handle => handle.callback());
        });
    }

    protected unbindEvent(control: Control): void {
        super.unbindEvent(control);
        control.onPointerClickObservable.clear();
    }

}


/**
 * 创建按钮控件
 * @param name 名称
 * @param scene 所在场景
 * @param options 参数对象
 * @param clickCallback 点击回调函数
 * @returns 按钮控件
 */
const CreateUIButton = (name: string, scene: Scene, options?: IUIButtonOptions, clickCallback?: { (): void }): UIButton => {
    const btn = new UIButton(name, scene, options);
    if (clickCallback) btn.onClick(clickCallback);
    return btn;
};


export { UIButton, CreateUIButton };
export type { IUIButtonOptions };